package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.conn.GuiGuCache;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.user.context.UpdateUserPaidRecordStrategyContext;
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
import com.atguigu.tingshu.user.mapper.UserPaidAlbumMapper;
import com.atguigu.tingshu.user.mapper.UserPaidTrackMapper;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.service.UserPaidTrackService;
import com.atguigu.tingshu.user.strategy.UpdateUserPaidRecordStrategy;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private KafkaService kafkaService;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;

    @Override
    public String wxLogin(String code) {



        try {
            //发送请求,校验凭证
            WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
            String openid = session.getOpenid();

            //条件查询,根据openId在userInfo表中查询是否注册
            LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserInfo::getWxOpenId, openid);
            UserInfo userInfo = userInfoMapper.selectOne(queryWrapper);


            // 如果该用户不存在
            if (userInfo == null) {
                userInfo = new UserInfo();
                userInfo.setWxOpenId(openid);
                userInfo.setNickname("听友" + UUID.randomUUID().toString().replaceAll("-",""));
                userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
                userInfoMapper.insert(userInfo);

                //只需要把用户id发送过去,然后再service-account服务中进行user_account的初始化
                kafkaService.sendMessage(KafkaConstant.QUEUE_USER_REGISTER, userInfo.getId().toString());
            }

            String token = UUID.randomUUID().toString().replaceAll("-", "");

            userInfo.setPassword(null);
            redisTemplate.opsForValue().set(RedisConstant.USER_LOGIN_KEY_PREFIX + token, JSON.toJSONString(userInfo));


            return token;

        } catch (Exception e) {
            e.printStackTrace();
            throw new GuiguException(ResultCodeEnum.LOGIN_ERROR);
        }
    }

    @Override
    public UserInfoVo getUserInfo() {

        Long userId = AuthContextHolder.getUserId();
        UserInfo userInfo = userInfoMapper.selectById(userId);
        UserInfoVo userInfoVo = new UserInfoVo();
        userInfoVo.setId(userId);
        userInfoVo.setWxOpenId(userInfo.getWxOpenId());
        userInfoVo.setNickname(userInfo.getNickname());
        userInfoVo.setAvatarUrl(userInfo.getAvatarUrl());
        userInfoVo.setIsVip(userInfo.getIsVip());
        userInfoVo.setVipExpireTime(userInfo.getVipExpireTime());
        return userInfoVo;
    }

    @Override
    public void updateUser(UserInfoVo userInfoVo) {
        Long userId = AuthContextHolder.getUserId();
        UserInfo userInfo = userInfoMapper.selectById(userId);
        userInfo.setNickname(userInfoVo.getNickname());
        userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
        userInfoMapper.updateById(userInfo);

    }
    //根据userId查询用户信息
    @Override
    public UserInfo getUserInfoById(Long userId) {
        return userInfoMapper.selectById(userId);
    }

    @GuiGuCache(cacheKey = "user:info:"+"#{#params[0]}")
    @Override
    public UserInfoVo findUserInfoVoByUserId(Long userId) {

        UserInfo userInfo = userInfoMapper.selectById(userId);
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo,userInfoVo);
        return userInfoVo;
    }


    //判断用户是否购买声音列表
    @Override
    public Map<Long, Integer> userIsPaidAlbumAndTrack(Long albumId, List<Long> trackIds) {

        //根据userId和albumId查询当前用户的这个专辑是否购买过
        Long userId = AuthContextHolder.getUserId();
        LambdaQueryWrapper<UserPaidAlbum> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserPaidAlbum::getUserId,userId)
                .eq(UserPaidAlbum::getAlbumId,albumId);
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(lambdaQueryWrapper);


        Map<Long,Integer> map = new HashMap<>();
        //如果购买过,则将这个专辑中的声音都设置为1
        if (userPaidAlbum !=null){
            trackIds.forEach(trackId ->{
                map.put(trackId,1);
            });
    }
        else {
            //是否购买过这张专辑中的声音
            LambdaQueryWrapper< UserPaidTrack> userPaidTrackLambdaQueryWrapper = new LambdaQueryWrapper<>();
            userPaidTrackLambdaQueryWrapper.eq(UserPaidTrack::getUserId,userId)
                    .eq(UserPaidTrack::getAlbumId,albumId);
            List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(userPaidTrackLambdaQueryWrapper);

            //如果表中数据为空,则表示没有购买过声音
            if (userPaidTracks == null){
                trackIds.stream().forEach(trackId -> {
                    map.put(trackId,0);
                });
            }else {
                List<Long> userPaidTrackIds = userPaidTracks.stream().map(userPaidTrack -> userPaidTrack.getId()).collect(Collectors.toList());
                trackIds.forEach(trackId ->{
                    if (userPaidTrackIds.contains(trackId)){
                        map.put(trackId,1);  // 购买过当前声音
                    }else {
                        map.put(trackId,0);// 未购买过声音
                    }
                });
            }
        }


        return map;
    }
    //判断用户是否购买过专辑
    @Override
    public Boolean isPaidAlbum(Long albumId) {

        //获取用户id
        Long userId = AuthContextHolder.getUserId();

        LambdaQueryWrapper<UserPaidAlbum> query = new LambdaQueryWrapper<UserPaidAlbum>();
        query.eq(UserPaidAlbum::getAlbumId,albumId)
                .eq(UserPaidAlbum::getUserId,userId);
        Long count = userPaidAlbumMapper.selectCount(query);


        return count > 0;
    }

    //远程调用:根据专辑id获取用户支付过的声音id列表
    @Override
    public List<Long> findUserPaidTrackList(Long albumId) {

        Long userId = AuthContextHolder.getUserId();
        LambdaQueryWrapper<UserPaidTrack> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserPaidTrack::getAlbumId,albumId)
                .eq(UserPaidTrack::getUserId,userId);
        List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(lambdaQueryWrapper);
        List<Long> trackIds = userPaidTracks.stream().map(userPaidTrack -> userPaidTrack.getTrackId()).collect(Collectors.toList());
        return trackIds;
    }

    @Override
    public void updateUserPaidRecord(UserPaidRecordVo userPaidRecordVo) {
        // 根据付款项目的类型保存交易信息【策略设计模式进行改造】
        String itemType = userPaidRecordVo.getItemType();
        UpdateUserPaidRecordStrategy updateUserPaidRecordStrategy = UpdateUserPaidRecordStrategyContext.getUpdateUserPaidRecordStrategy(itemType);
        updateUserPaidRecordStrategy.updateUserPaidRecord(userPaidRecordVo) ;
    }


}
